#pragma once
#include "..\utils\GameMath.h"
#include <vector>
#include "..\nodes\Node.h"
#include "..\renderer\IndexVertexBuffer.h"
#include "..\renderer\VertexDeclaration.h"
#include <string>
#include "..\base\Controller.h"
#include "..\content\ResManager.h"

namespace ds {

// ---------------------------------------------------------------
//
// ---------------------------------------------------------------
class ConsoleParameters {

typedef std::vector<std::string> Items;

public:
	ConsoleParameters(std::string line);
	~ConsoleParameters(void);
	std::string get(int index);
	std::string getCommand() { return command;}
	float getFloat(int index);
	Vec3 getVec3(int index);
	Vec2 getVec2(int index);
	int getInt(int index);
private:
	void splitLine();
	template<class T> T fromString(const std::string& s);
	std::string commandLine;
	std::string command;
	Items items;
};

typedef bool (*consoleFunctionPointer) (const ConsoleParameters& cp,std::string* errorMessage);

// ---------------------------------------------------------------
//
// ---------------------------------------------------------------
class GameConsoleListener {

public:
	virtual void onSubmit(const ConsoleParameters& params) = 0;
};

// ---------------------------------------------------------------
// Console command prototypes
// ---------------------------------------------------------------
bool consoleStopUpdates(const ConsoleParameters& parameters,std::string* message);
bool consoleSetCVar(const ConsoleParameters& parameters,std::string* message);
bool consoleSaveCVar(const ConsoleParameters& parameters,std::string* message);
bool consoleLoadCVar(const ConsoleParameters& parameters,std::string* message);
bool consolePlaySound(const ConsoleParameters& parameters,std::string* message);
bool consoleShowLayers(const ConsoleParameters& parameters,std::string* message);
bool consoleReloadShader(const ConsoleParameters& parameters,std::string* message);

// ---------------------------------------------------------------
//
// ---------------------------------------------------------------
class GameConsole : public Node, public KeyboardController {
	
typedef std::vector<std::string> Lines;
typedef std::vector<std::string>::iterator LineIterator;
typedef std::vector<GameConsoleListener*> Listeners;
typedef std::map<std::string,consoleFunctionPointer> Functions;

public:
	GameConsole(const Vec2& startPos,const Vec2& size,UINT lines,UINT historySize) : Node("GameConsole","ConsoleMaterial",true) ,
		m_StartPos(startPos) , m_Size(size) , m_TotalLines(lines) , m_HistoryIdx(0) , m_HistorySize(historySize)
	{
		gEngine->addController(this);
		m_Functions["toggle_updates"] = consoleStopUpdates;
		m_Functions["set"] = consoleSetCVar;
		m_Functions["save"] = consoleSaveCVar;
		m_Functions["load"] = consoleLoadCVar;
		m_Functions["sound"] = consolePlaySound;
		m_Functions["debug_layers"] = consoleShowLayers;
		m_Functions["reload_shader"] = consoleReloadShader;
	}
	~GameConsole(void);	
	void init();
	void loadContent(ResManager& resourceManager) {}
	void rebuild();
	void prepareRendering();
	void draw();
	void toggle() {
		setActive(!m_Active);
	}
	//
	void OnKeyUp( WPARAM virtualKeyCode );
	void OnKeyDown( WPARAM virtualKeyCode ) {}
	void OnChar(char ascii,unsigned int keyState);
	//
	void addListener(GameConsoleListener* listener) {
		m_Listeners.push_back(listener);
	}
private:		
	void addChar(char ascii);
	void processLine();
	//
	IndexVertexBuffer<TransformedTexturedVertex>* m_Buffer;
	LPD3DXSPRITE m_Sprite;
	std::string m_CurrentLine;
	Lines m_Lines;
	Vec2 m_StartPos;
	Vec2 m_Size;
	UINT m_TotalLines;
	Listeners m_Listeners;
	UINT m_HistoryIdx;
	UINT m_HistorySize;
	Functions m_Functions;
};

}

